package org.wak.dialog.sci
{
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	
	import org.wak.dialog.AdventureDialog;
	import org.wak.dialog.Topic;
	import org.wak.dialog.event.TextSelectedEvent;
	import org.wak.main.AdventureMaster;
	import org.wak.utils.IIterator;
	import org.wak.utils.WakSimpleButton;

	/**
	 * Display a SCI style dialog options menu. 
	 */	
	public class SciDialogMenu extends Sprite
	{
		public static const TEXT_SELECTED:String = "text_selected" ;
		
		// the represented dialog.
		private var mDialog:AdventureDialog = null ;
		private var mOptionHeight:Number = 100 ;
		private var mOptionWidth:Number = 100 ;
		
		private var mBackground:DisplayObject = null ;
		
		private var mWidth:Number = 100 ;
		private var mHeight:Number = 100 ;
		
		/// array of dialog options.
		private var mOptionsArray:Array = null ;
		/// Asoc array of dialog options by Id.
		private var mOptionsByIdArray:Array = null ;
		
		// array of topics
		private var mTopicsArray:Array = null ;
		
		private var mMenuSeparatorY:Number = 5 ;
		
		private var mUpTextFormat:TextFormat = null ;
		private var mOverTextFormat:TextFormat = null ;
		
		private var mPlayerCharId:String = "";
		
		private var mBulletsArray:Array = null ;
		
		
		//configurable attributes.
		private var mConfBgColor:uint = 0xE9D494 ;
		
		private var mConfLeftMargin:int = 10 ;
		private var mConfLeftBulletMargin:int = 10 ;
		
		private var mConfTopMargin:int = 10 ;
		
		private var mConfBulletAsset:Class = null ;
		
		private var mConfBulletYOffset:int = 8 ; 
		
		
		/**
		 * Constructor 
		 * @param pDialog AdventureDialog to display
		 * @param pBg Menu Background.
		 * @param pMenuOptionWidth width of a text options in pixels
		 * @param pMenuOptionHeight height of a text options in pixels
		 * @param pFont font name to use in the options
		 * @param pUpColor color used in the options for the up state.
		 * @param pOverColor color used in the options for the over state.
		 * @param pSize size of the font in the options.
		 * @param pBold bold the font used in the option.
		 * 
		 */	
		public function SciDialogMenu(pDialog:AdventureDialog, pBg:DisplayObject, pMenuOptionWidth:Number, pMenuOptionHeight:Number, 
								   pFont:String = "acknowtt", pUpColor:uint = 0x000000, pOverColor:uint = 0xFF0000,
								   pSize:int = 13 ,pBold:Boolean = true, pEmbedFont:Boolean = true)
		{
			super();
			mDialog = pDialog ;
			mBackground = pBg ;
			mOptionHeight = pMenuOptionHeight ;
			mOptionWidth = pMenuOptionWidth ;
			mOptionsArray = new Array();
			mOptionsByIdArray = new Array();
			mTopicsArray = new Array();
			
			mBulletsArray = new Array();
			
			mPlayerCharId = AdventureMaster.defaultPlayerCharacterId ;
			
			mUpTextFormat = new TextFormat();
			mUpTextFormat.align = TextFormatAlign.LEFT ;
			mUpTextFormat.font = pFont ;
			mUpTextFormat.color = pUpColor ;
			mUpTextFormat.bold = pBold ;
			mUpTextFormat.size = pSize ;
			
			mOverTextFormat = new TextFormat();
			mOverTextFormat.align = mUpTextFormat.align ;
			mOverTextFormat.font = mUpTextFormat.font ;
			mOverTextFormat.color = pOverColor;
			mOverTextFormat.bold = mUpTextFormat.bold ;
			mOverTextFormat.size = mUpTextFormat.size ;
			
			var fUp:TextField = null ;
			var fOver:TextField = null ;
			var fDown:TextField = null ;
			
			var fNewButton:WakSimpleButton = null ;
			var fTopic:Topic = null ;
			var fOptionsIterator:IIterator = mDialog.GetTopics() ;
			
			while( fOptionsIterator.hasNext() )
			{
				fUp = new TextField();
				fUp.embedFonts = pEmbedFont ;
				fUp.defaultTextFormat = mUpTextFormat ;
				fUp.width = mOptionWidth ;
				fUp.height = mOptionHeight ;
				fUp.wordWrap = true ;
				//fUp.textColor = 0xFFFFFF ;
				fUp.selectable = false ;
				
				fOver = new TextField();
				fOver.embedFonts = fUp.embedFonts ;
				fOver.defaultTextFormat = mOverTextFormat ;
				fOver.width = mOptionWidth ;
				fOver.height = mOptionHeight ;
				fOver.wordWrap = true ;
				//fOver.textColor = 0xFF0000 ;
				fOver.selectable = false ;
				
				fDown = new TextField();
				fDown.embedFonts = fUp.embedFonts ;
				fDown.defaultTextFormat = mOverTextFormat ;
				fDown.width = mOptionWidth ;
				fDown.height = mOptionHeight ;
				fDown.wordWrap = true ;
				//fDown.textColor = 0xFFFFFF ;
				fDown.selectable = false ;
				
				fTopic = fOptionsIterator.next() as Topic ;
				
				
				fUp.text = fTopic.SayText(mPlayerCharId) ;
				fOver.text = fTopic.SayText(mPlayerCharId) ;
				fDown.text = fTopic.SayText(mPlayerCharId) ;
				
				fNewButton = new WakSimpleButton(fUp,fOver,fDown) ;
				mOptionsArray.push(fNewButton);
				mTopicsArray.push(fTopic);
				
				if(fTopic.topicId != "")
					mOptionsByIdArray[fTopic.topicId] = fNewButton ;
				
				if(!fTopic.visible)
					fNewButton.visible = false ;
			}
			
			this.addEventListener(Event.ADDED_TO_STAGE, OnAddedToStage);
		}
		
		/**
		 * Activates or disable a dialog option asociated to the topic id in pTopicId 
		 * @param pTopicId topic id to activate.
		 * 
		 */		
		public function SetOptionVisible(pTopicId:String, value:Boolean ):void
		{
			var fOption:WakSimpleButton = mOptionsByIdArray[pTopicId] as WakSimpleButton ;
			
			if(fOption == null)
				return ;
			
			fOption.visible = value ;
			RefreshOptionsButtonPositions();
		}
		
		/**
		 * Sets the dimensions of the default drawn background when no image is provided. 
		 * @param pW width of the background.
		 * @param pH height of the background.
		 * 
		 */		
		public function SetDefaultBgSize( pW:Number, pH:Number):void
		{
			mWidth = pW ;
			mHeight = pH
		}
		
		private function OnAddedToStage(event:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE, OnAddedToStage);
			
			if( mBackground == null )
			{
				var fBgShape:Shape = new Shape();
				fBgShape.graphics.beginFill(mConfBgColor,1);
				fBgShape.graphics.drawRect(0,0,mWidth, mHeight);
				fBgShape.graphics.endFill();
				
				fBgShape.graphics.lineStyle(1,0x000000);
				fBgShape.graphics.drawRect(0,0,mWidth, mHeight);
				fBgShape.graphics.endFill();
				mBackground = fBgShape ;				
			}
			this.addChild( mBackground );
			
			AddOptionsButton();
			
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE,OnMouseMove );
			
			this.addEventListener(Event.REMOVED_FROM_STAGE,OnRemovedFromStage );
		}
		
		private function OnRemovedFromStage(event:Event):void
		{
			this.removeEventListener(Event.REMOVED_FROM_STAGE, OnAddedToStage);
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE,OnMouseMove );
			
			this.addEventListener(Event.ADDED_TO_STAGE, OnAddedToStage);
		}
		
		private function OnMouseMove(event:MouseEvent):void
		{
			for each( var option:WakSimpleButton in mOptionsArray)
			{
				option.Update( event.stageX, event.stageY);
			}
		}
		
		private function AddOptionsButton():void
		{
			var fCurrentY:Number = mConfTopMargin ;
			var fBullet:DisplayObject = null ;
			
			for each( var option:WakSimpleButton in mOptionsArray)
			{
				if(option.visible)
				{
					if( mConfBulletAsset == null )
					{
						fBullet = CreateDefaultBullet();	
					}
					else
					{
						fBullet = new mConfBulletAsset();
					}
					addChild(option);
					fBullet.x = mConfLeftMargin
					option.x = fBullet.x + mConfLeftBulletMargin ;
					option.y = fCurrentY ;
					fBullet.y = option.y + mConfBulletYOffset ;
					fCurrentY += option.height + mMenuSeparatorY;
					option.addEventListener( MouseEvent.MOUSE_UP, OnOptionClicked);
					this.addChild(fBullet);
					mBulletsArray[option.name] = fBullet ;
				}
			}
		}
		
		private function CreateDefaultBullet():Sprite
		{
			var fRet:Sprite = new Sprite();
			
			fRet.graphics.beginFill(0x000000,1);
			fRet.graphics.drawCircle(0,0,2);
			fRet.graphics.endFill() ;
			
			return fRet ;
		}
		
		private function RefreshOptionsButtonPositions():void
		{
			var fCurrentY:Number = mConfTopMargin ;
			var fBullet:DisplayObject = null ;
			
			for each( var option:WakSimpleButton in mOptionsArray)
			{
				if(option.visible)
				{
					option.y = fCurrentY ;
					if(!this.contains(option) )
					{
						if( mConfBulletAsset == null )
						{
							fBullet = CreateDefaultBullet();	
						}
						else
						{
							fBullet = new mConfBulletAsset();
						}
						fBullet.x = mConfLeftMargin
						option.x = fBullet.x + mConfLeftBulletMargin ;
						fBullet.y = option.y + mConfBulletYOffset ;
						this.addChild(fBullet);
						mBulletsArray[option.name] = fBullet;
						
						
						addChild(option);
						option.addEventListener(MouseEvent.MOUSE_UP, OnOptionClicked);
					}
					else
					{
						fBullet = mBulletsArray[option.name] ;
						fBullet.y = option.y + mConfBulletYOffset ;
					}
					
					fCurrentY += option.height + mMenuSeparatorY;
				}
			}
		}
		
		private function OnOptionClicked(event:MouseEvent):void
		{
			var fSelected:WakSimpleButton = event.currentTarget as WakSimpleButton ;
			
			if(fSelected == null)
				return ;
			
			var fIndex:int = mOptionsArray.indexOf( fSelected );
			var fTopic:Topic = mTopicsArray[fIndex] ;
			
			var fEvent:Event = new TextSelectedEvent( TEXT_SELECTED, fTopic);
			this.dispatchEvent(fEvent);
			
		}
		
	
		/**
		 * Set the margins to the left of the options 
		 * @param pBulletMargin space between the bullet and the text option.
		 * @param pLeftMargin space between the left border and the bullet.
		 * 
		 */	
		public function SetMargins( pBulletMargin:Number, pLeftMargin:Number):void
		{
			mConfLeftBulletMargin = pBulletMargin ;
			mConfLeftMargin = pLeftMargin ;
		}
	
		/**
		 * Set the asset for the bullet before the text option. 
		 * @param pBullet class to create a DisplayObject as bullet.
		 * 
		 */		
		public function SetBulletAsset( pBullet:Class ):void
		{
			mConfBulletAsset = pBullet ;
		}
		
		/**
		 * Set the color used to draw the background when no image is provided. 
		 * @param pColor background color.
		 * 
		 */		
		public function SetDefaultBgColor(pColor:uint):void
		{
			mConfBgColor = pColor
		}
		
	}
}